package com.lse_from.utils

import com.baomidou.mybatisplus.annotation.DbType
import com.baomidou.mybatisplus.generator.AutoGenerator
import com.baomidou.mybatisplus.generator.InjectionConfig
import com.baomidou.mybatisplus.generator.config.*
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType
import com.baomidou.mybatisplus.generator.config.rules.IColumnType
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy
import java.util.*

/**
 * mybatis plus kotlin逆向生成
 * @author 祁雪
 */
class MpGenerator {

    companion object {

        // 生成的文件存储位置
        var outpath = "D:\\project\\IdeaWork/lse_from/src/main/kotlin/";

        // 生成的文件作者
        var author = "祁雪"

        // 数据库引擎
        var driverName = "org.postgresql.Driver";

        // 数据库用户
        var user = "postgres"

        // 数据库密码
        var passWord = "qixue201314"

        // 数据库名称
        var databaseName = ""

        // 数据库连接地址
        var url =
            "jdbc:postgresql://127.0.0.1:5432/${databaseName}"

        var tableNames = arrayOf<String>()

        // 父包位置
        var parentPath = "com.lse_from"

        // 异常类(这里用的自定义异常返回)
        var exceptionPath = "com.lse_from.exception.LseException"

        var dbType = DbType.POSTGRE_SQL

        /**
         * 开始执行代码生成
         *
         * @param tableNames
         */
        fun MpGeneratorGo(
            tableNames: Array<String>,
            isFileOverride: Boolean
        ) {
            val mpg = AutoGenerator()

            // 全局配置
            val gc = GlobalConfig()
            // 是否使用kotlin
            gc.isKotlin = true
            gc.outputDir = outpath
            gc.isFileOverride = isFileOverride //是否覆盖已有文件
            gc.isActiveRecord = false
            gc.isEnableCache = false // XML 二级缓存
            gc.isBaseResultMap = true // XML ResultMap
            gc.isBaseColumnList = true // XML columList
            gc.author = author

            // 自定义文件命名，注意 %s 会自动填充表实体属性！
            gc.mapperName = "%sMapper"
            gc.xmlName = "%sMapper"
            gc.serviceName = "%sService"
            gc.serviceImplName = "%sServiceImpl"
//            gc.controllerName = "%sController"
            mpg.globalConfig = gc

            // 数据源配置
            val dsc = DataSourceConfig()
            dsc.dbType = dbType
            dsc.typeConvert = object : MySqlTypeConvert() {
                override fun processTypeConvert(globalConfig: GlobalConfig, fieldType: String): DbColumnType {
                    println("转换类型：$fieldType")
                    //将数据库中datetime转换成date
                    return if ("datetime".equals(fieldType, true)) {
                        DbColumnType.DATE
                    } else super.processTypeConvert(globalConfig, fieldType) as DbColumnType
                } /*@Override
                 public DbColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
                     System.out.println("转换类型：" + fieldType);
                     return (DbColumnType) super.processTypeConvert(globalConfig, fieldType);
                 }*/
            }
            dsc.driverName = driverName
            dsc.username = user
            dsc.password = passWord
            dsc.url = url
            mpg.dataSource = dsc

            // 策略配置
            val strategy = StrategyConfig()
            // 全局大写命名 ORACLE 注意
            // strategy.setCapitalMode(true);
            //strategy.setTablePrefix(new String[] { "sys_", "ql_" });// 此处可以修改为您的表前缀
            //strategy.setTablePrefix(new String[] {"ejar_","gc_"});
            strategy.naming = NamingStrategy.underline_to_camel // 表名生成策略 取消下划线并下划线后第一个字母大写
            // strategy.setNaming(NamingStrategy.nochange);// 表名生成策略 原样生成
            strategy.setInclude(*tableNames) // 需要生成的表
            // strategy.setExclude(new String[]{"test"}); // 排除生成的表
            strategy.superControllerClass = exceptionPath
            /*      // 【实体】是否生成字段常量（默认 false）
         public static final String ID = "test_id";
         strategy.setEntityColumnConstant(true);
        // 【实体】是否为构建者模型（默认 false）
         public User setName(String name) {this.name = name; return this;}
         strategy.setEntityBuilderModel(true);*/
            mpg.strategy = strategy

            // 包配置
            val pc = PackageConfig()
            pc.parent = parentPath
            pc.controller = "control"
            pc.entity = "dto"
            pc.service = "service"
            pc.serviceImpl = "service.impl"
            pc.mapper = "mapper"
            pc.xml = "mapper.xml"
            mpg.packageInfo = pc

            // 注入自定义配置，可以在 VM 中使用 cfg.abc 【可无】
            val cfg: InjectionConfig = object : InjectionConfig() {
                override fun initMap() {
                    val map: MutableMap<String, Any> = HashMap()
                    map["key"] = config.globalConfig.author + "-done"
                    this.map = map
                }
            }
            mpg.cfg = cfg
            // 注入kotlin 模板 不想生成某块内容则设为null
            val templateConfig = TemplateConfig()
            templateConfig.controller = null

            mpg.template = templateConfig
            // 执行生成
            mpg.execute()

            // 打印注入设置【可无】
            println(mpg.cfg.map["key"])
        }

    }

}

fun main() {
    MpGenerator.databaseName = "lse_from"
    MpGenerator.tableNames = arrayOf("from_field", "from_data")
    MpGenerator.url =
        "jdbc:postgresql://127.0.0.1:5432/${MpGenerator.databaseName}"
    MpGenerator.MpGeneratorGo(
        MpGenerator.tableNames,
        false
    )
}